package com.redball.ams.service.impl;


import com.redball.ams.common.model.PageObject;
import com.redball.ams.common.util.ValidUitls;
import com.redball.ams.dao.SysUserDao;
import com.redball.ams.dao.SysUserRoleDao;
import com.redball.ams.model.SysUser;
import com.redball.ams.model.SysUserDept;
import com.redball.ams.service.SysUserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

//Transactional注解描述的方法为事务切入点方法,这个方法在执行之前会开启事务,方法执行之后会提交或回滚事务
@Transactional(readOnly = false,
        rollbackFor =Throwable.class,
        timeout = 60,
        isolation = Isolation.READ_COMMITTED,
        propagation = Propagation.REQUIRED)
@Service
public class SysUserServiceImpl implements SysUserService {
    @Autowired
    private SysUserDao sysUserDao;

    @Autowired
    private SysUserRoleDao sysUserRoleDao;

    @Override
    public int updatePassword(String newPassword, String cfgPassword, String sourcePassword) {
        //1.参数校验(非空,规则,正确)
        ValidUitls.isArgsValid(StringUtils.isEmpty(sourcePassword), "原密码不能为空");
        ValidUitls.isArgsValid(StringUtils.isEmpty(newPassword), "新密码不能为空");
        ValidUitls.isArgsValid(!newPassword.equals(cfgPassword), "两次输入的新密码不一致");
        //验证原密码是否正确
        SysUser user=(SysUser) SecurityUtils.getSubject().getPrincipal();
        SimpleHash sh=new SimpleHash("MD5",sourcePassword,user.getSalt(),1);
        ValidUitls.isArgsValid(!user.getPassword().equals(sh.toHex()),"原密码不正确");
        //2.修改密码(新盐值,新密码加密,修改)
        String newSalt=UUID.randomUUID().toString();
        sh=new SimpleHash("MD5",newPassword,newSalt,1);
        String newHashedPassword=sh.toHex();
        int rows=sysUserDao.updatePassword(user.getUsername(),newHashedPassword,newSalt);
        ValidUitls.isResultValid(rows==0, "记录可能已经不存在了");
        return rows;
    }

    //方法上事务特性优先级要高于类上定义的事务特性.

    @Transactional(readOnly = true)//建议所有查询操作,事务的readOnly属性值改为true
    @Override
    public Map<String, Object> findObjectById(Integer id) {
        //1.参数校验
        //2.查询用户以及用户对应的部门信息
        SysUserDept user=sysUserDao.findObjectById(id);
        //3.查询用户对应的角色信息
        List<Integer> roleIds=sysUserRoleDao.findRoleIdsByUserId(id);
        //4.封装查询结果并返回
        Map<String,Object> map=new HashMap<>();
        map.put("user", user);
        map.put("roleIds", roleIds);
        return map;
    }

    @Override
    public int updateObject(SysUser entity, Integer[] roleIds) {
        //1.参数校验
        ValidUitls.isArgsValid(entity==null,"保存对象不能为空");
        String username=entity.getUsername();
        ValidUitls.isArgsValid(username==null||"".equals(username),"用户名不能为空");
        ValidUitls.isArgsValid(roleIds==null||roleIds.length==0, "必须为用户分配一个角色");
        //......
        //2.保存用户自身信息
        int rows=sysUserDao.updateObject(entity);
        ValidUitls.isResultValid(rows==0,"记录可能已经不存在了");
        //3.保存用户和角色关系数据
        sysUserRoleDao.deleteObjectsByUserId(entity.getId());
        sysUserRoleDao.insertObjects(entity.getId(), roleIds);
        return rows;
    }
    @Override
    public int saveObject(SysUser entity, Integer[] roleIds) {
        //1.参数校验
        ValidUitls.isArgsValid(entity==null,"保存对象不能为空");
        String username=entity.getUsername();
        ValidUitls.isArgsValid(username==null||"".equals(username),"用户名不能为空");
        String password=entity.getPassword();
        ValidUitls.isArgsValid(password==null||"".equals(password), "密码不能为空");
        ValidUitls.isArgsValid(roleIds==null||roleIds.length==0, "必须为用户分配一个角色");
        //......
        //2.保存用户自身信息
        //2.1对密码进行加密
        String salt= UUID.randomUUID().toString();//产生随机字符串,让此字符串作为一个加密盐
        //String newPwd=DigestUtils.md5DigestAsHex((password+salt).getBytes());//Spring自带
        SimpleHash sh=new SimpleHash("MD5", password, salt, 1);
        String newPwd=sh.toHex();
        //2.2将盐值和密码存储到entity对象
        entity.setSalt(salt);
        entity.setPassword(newPwd);
        int rows=sysUserDao.insertObject(entity);
        //3.保存用户和角色关系数据
        sysUserRoleDao.insertObjects(entity.getId(), roleIds);
        return rows;
    }

    @Override
    public int validById(Integer id, Integer valid) {
        //1.参数校验
        //2.修改状态
        int rows=sysUserDao.validById(id, valid,"admin");
        //3.判断并返回结果
        ValidUitls.isResultValid(rows==0, "记录可能已经不存在");
        return rows;
    }


    @Override
    public PageObject<SysUserDept> findPageObjects(String username, Integer pageCurrent) {
        //1.参数校验
        ValidUitls.isArgsValid(pageCurrent==null||pageCurrent<1, "页码值不正确");
        //2.查询记录数并校验
        int rowCount=sysUserDao.getRowCount(username);
        ValidUitls.isResultValid(rowCount==0, "没有找到对应的记录");
        //3.查询当前页记录
        int pageSize=5;
        int startIndex=(pageCurrent-1)*pageSize;
        List<SysUserDept> records= sysUserDao.findPageObjects(username, startIndex,pageSize);
        //4.封装查询结果
        return new PageObject<>(rowCount, records, pageCurrent, pageSize);
    }
}
